﻿using ezCloud.Data;
using ezCloud.Data.Enum;
using ezCloud.SendEmailMarketingBySchedule.Core;
using Quartz;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace ezCloud.SendEmailMarketingBySchedule.Job
{
    public class CreateTemplateEmailJob : IJob
    {
        #region Properties

        private ezCloudDataContext DataContext = new ezCloudDataContext();
        private DateTime currentDate = DateTime.UtcNow;

        #endregion
        public void Execute(IJobExecutionContext context)
        {
            List<HotelEmailLog> listEmailLog = new List<HotelEmailLog>();

            listEmailLog.AddRange(GetListTravellerForBefore());
            listEmailLog.AddRange(GetListTravellerForAfter());
            listEmailLog.AddRange(GetListTravellerForInHouse());

            if (listEmailLog.Count > 0)
            {
                listEmailLog.ForEach(x =>
                {
                    string linkFileTxt;
                    CreateTemplateEmailById(x, out linkFileTxt);
                    x.Link = linkFileTxt;
                    x.CreatedAt = DateTime.UtcNow;
                });
            }
            DataContext.HotelEmailLog.InsertAllOnSubmit(listEmailLog);
            //DataContext.SubmitChanges();
        }
        #region Private Methods
        private void CreateTemplateEmailById(HotelEmailLog hotelEmailLog, out string linkfileText)
        {
            string bodyEmail = "";
            bodyEmail = DataContext.HotelEmailTask.Where(x => x.HotelEmailTaskId == hotelEmailLog.HotelEmailTaskId).FirstOrDefault().Body;

            bodyEmail = replaceHotelFieldValue(hotelEmailLog.Hotels, bodyEmail);
            bodyEmail = replaceGuestFieldValue(hotelEmailLog.Travellers, bodyEmail);
            bodyEmail = replaceBookingInformationValue(hotelEmailLog.ReservationRooms, bodyEmail);
            bodyEmail = replaceGeneralValue(bodyEmail);

            var dir = SystemConfiguration.DIRECTION_EMAIL_TEMPLATE;

            dir = Path.Combine(dir, currentDate.Year.ToString(), currentDate.Month.ToString(), currentDate.Day.ToString());

            if (!Directory.Exists(dir))  // if it doesn't exist, create
                Directory.CreateDirectory(dir);

            string fileName = DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".txt";

            linkfileText = Path.Combine(dir, fileName);
            File.WriteAllText(linkfileText, bodyEmail);
        }
        #region replace value config
        private string replaceGeneralValue(string result)
        {
            var generalEnum = typeof(Data.Enum.General);

            var generalDate = CreateValueFieldReplaceInTemp(generalEnum, (int)Data.Enum.General.CurrentDate);
            result = result.Replace(generalDate, currentDate.ToString("dd-mm-yyyy"));

            var generalSig = CreateValueFieldReplaceInTemp(generalEnum, (int)Data.Enum.General.Signature);
            result = result.Replace(generalSig, "");

            return result;
        }

        private string replaceBookingInformationValue(ReservationRooms reservationRooms, string result)
        {
            var bookingEnum = typeof(Data.Enum.BookingInformation);

            var bookingCheckin = CreateValueFieldReplaceInTemp(bookingEnum, (int)Data.Enum.BookingInformation.CheckinDate);
            if (reservationRooms.CheckInDate.HasValue)
            {
                result = result.Replace(bookingCheckin, reservationRooms.CheckInDate.Value.ToString("dd-mm-yyyy"));
            }

            var bookingCheckout = CreateValueFieldReplaceInTemp(bookingEnum, (int)Data.Enum.BookingInformation.CheckoutDate);
            if (reservationRooms.CheckOutDate.HasValue)
            {
                result = result.Replace(bookingCheckout, reservationRooms.CheckOutDate.Value.ToString("dd-mm-yyyy"));
            }

            var bookingNo = CreateValueFieldReplaceInTemp(bookingEnum, (int)Data.Enum.BookingInformation.ReservationNo);
            result = result.Replace(bookingNo, reservationRooms.Reservations.ReservationNumber.Value.ToString());

            var bookingAdult = CreateValueFieldReplaceInTemp(bookingEnum, (int)Data.Enum.BookingInformation.Adult);
            result = result.Replace(bookingAdult, reservationRooms.Adults.ToString());

            var bookingChild = CreateValueFieldReplaceInTemp(bookingEnum, (int)Data.Enum.BookingInformation.Child);
            result = result.Replace(bookingChild, reservationRooms.Child.ToString());

            var bookingAmount = CreateValueFieldReplaceInTemp(bookingEnum, (int)Data.Enum.BookingInformation.TotalAmount);
            result = result.Replace(bookingAmount, reservationRooms.Price.ToString());

            var bookingPaid = CreateValueFieldReplaceInTemp(bookingEnum, (int)Data.Enum.BookingInformation.TotalPaid);
            result = result.Replace(bookingPaid, reservationRooms.Price.ToString());

            var bookingCurrency = CreateValueFieldReplaceInTemp(bookingEnum, (int)Data.Enum.BookingInformation.Currency);
            //result = result.Replace(bookingCurrency, reservationRooms..ToString());

            var bookingRoomNo = CreateValueFieldReplaceInTemp(bookingEnum, (int)Data.Enum.BookingInformation.RoomNo);
            result = result.Replace(bookingAmount, reservationRooms.Reservations.ReservationRoomsList.Count.ToString());

            var bookingListRoom = CreateValueFieldReplaceInTemp(bookingEnum, (int)Data.Enum.BookingInformation.ListRoom);
            //result = result.Replace(bookingAmount, reservationRooms.Price.ToString());

            return result;
        }

        private string replaceGuestFieldValue(Travellers guest, string result)
        {
            var guestEnum = typeof(Data.Enum.Guests);

            var guestNames = CreateValueFieldReplaceInTemp(guestEnum, (int)Data.Enum.Guests.Guest_Name);
            result = result.Replace(guestNames, guest.Fullname);

            var guestAddress = CreateValueFieldReplaceInTemp(guestEnum, (int)Data.Enum.Guests.Guest_Address);
            result = result.Replace(guestAddress, guest.Address);

            var guestBirthday = CreateValueFieldReplaceInTemp(guestEnum, (int)Data.Enum.Guests.Guest_Birthday);
            if (guest.Birthday.HasValue)
            {
                result = result.Replace(guestBirthday, guest.Birthday.Value.ToString("dd-mm-yyyy"));
            }
            else
            {
                result = result.Replace(guestBirthday, "");
            }

            var guestSex = CreateValueFieldReplaceInTemp(guestEnum, (int)Data.Enum.Guests.Guest_Sex);
            var guestSexValue = guest.Gender == 1 ? "Nam" : "Nữ";
            result = result.Replace(guestSex, guestSexValue);

            var guestEmail = CreateValueFieldReplaceInTemp(guestEnum, (int)Data.Enum.Guests.Guest_Email);
            result = result.Replace(guestEmail, guest.Email);

            var guestPhone = CreateValueFieldReplaceInTemp(guestEnum, (int)Data.Enum.Guests.Guest_Phone);
            result = result.Replace(guestPhone, guest.Mobile);

            var guestNote = CreateValueFieldReplaceInTemp(guestEnum, (int)Data.Enum.Guests.Guest_Note);
            result = result.Replace(guestNote, guest.Note);

            var guestCountry = CreateValueFieldReplaceInTemp(guestEnum, (int)Data.Enum.Guests.Guest_Country);
            result = result.Replace(guestCountry, guest.Countries.CountryName);

            return result;
        }

        private string replaceHotelFieldValue(Data.Hotels hotel, string result)
        {
            var hotelEnum = typeof(Data.Enum.Hotels);

            var hotelNames = CreateValueFieldReplaceInTemp(hotelEnum, (int)Data.Enum.Hotels.Hotel_Name);
            result = result.Replace(hotelNames, hotel.HotelName);

            var hotelLogo = CreateValueFieldReplaceInTemp(hotelEnum, (int)Data.Enum.Hotels.Hotel_Logo);
            result = result.Replace(hotelLogo, hotel.HotelLogoUrl);

            var hotelPhone = CreateValueFieldReplaceInTemp(hotelEnum, (int)Data.Enum.Hotels.Hotel_Phone);
            result = result.Replace(hotelPhone, hotel.HotelPhone);

            var hotelEmail = CreateValueFieldReplaceInTemp(hotelEnum, (int)Data.Enum.Hotels.Hotel_Email);
            result = result.Replace(hotelEmail, hotel.HotelEmail);

            var hotelAddress = CreateValueFieldReplaceInTemp(hotelEnum, (int)Data.Enum.Hotels.Hotel_Address);
            result = result.Replace(hotelAddress, hotel.HotelAddress);

            var hotelWebsite = CreateValueFieldReplaceInTemp(hotelEnum, (int)Data.Enum.Hotels.Hotel_Website);
            result = result.Replace(hotelAddress, hotel.HotelWebsite);

            return result;
        }

        private string CreateValueFieldReplaceInTemp(Type enumType, int value)
        {
            string result = "";
            result = "{" + Enum.GetName(enumType, value) + "}";
            return result;
        }

        #endregion
        #region Get list traveller by rule
        private List<HotelEmailLog> GetListTravellerForInHouse()
        {
            List<HotelEmailLog> result = new List<HotelEmailLog>();
            List<HotelEmailTask> listTemp = DataContext.HotelEmailTask.Where(x => x.TypeId == 3).ToList();

            if (listTemp != null && listTemp.Count > 0)
            {
                listTemp.ForEach(x =>
                {
                    var listEmailLog = DataContext.ReservationRooms.Where(rr => rr.BookingStatus.ToUpper() == "checkin".ToUpper() && rr.HotelId == x.HotelId).Select(y => new HotelEmailLog
                    {
                        Email = y.Travellers.Email,
                        TravellerId = y.TravellerId,
                        HotelId = x.HotelId,
                        Status = (int)SendMailStatus.Processing,
                        HotelEmailTaskId = x.HotelEmailTaskId,
                        ReservationId = y.ReservationId,
                        ReservationRoomId = y.ReservationRoomId
                    }).ToList();
                    result.AddRange(listEmailLog);
                });
            }

            return result;
        }
        private List<HotelEmailLog> GetListTravellerForAfter()
        {
            List<HotelEmailLog> result = new List<HotelEmailLog>();
            List<HotelEmailTask> listTemp = DataContext.HotelEmailTask.Where(x => x.TypeId == 2).ToList();

            if (listTemp != null && listTemp.Count > 0)
            {
                listTemp.ForEach(x =>
                {
                    DateTime dateCompare = currentDate.AddDays(-x.Day.Value).Date;
                    var listEmailLog = DataContext.ReservationRooms.Where(rr => rr.BookingStatus.ToUpper() == "after".ToUpper() && rr.HotelId == x.HotelId && rr.ArrivalDate.Value.Date == dateCompare).Select(y => new HotelEmailLog
                    {
                        Email = y.Travellers.Email,
                        TravellerId = y.TravellerId,
                        HotelId = x.HotelId,
                        Status = (int)SendMailStatus.Processing,
                        HotelEmailTaskId = x.HotelEmailTaskId,
                        ReservationId = y.ReservationId,
                        ReservationRoomId = y.ReservationRoomId
                    }).ToList();
                    result.AddRange(listEmailLog);
                });
            }

            return result;
        }

        private List<HotelEmailLog> GetListTravellerForBefore()
        {
            List<HotelEmailLog> result = new List<HotelEmailLog>();
            List<HotelEmailTask> listTemp = DataContext.HotelEmailTask.Where(x => x.TypeId == 1).ToList();

            if (listTemp != null && listTemp.Count > 0)
            {
                listTemp.ForEach(x =>
                {
                    DateTime dateCompare = currentDate.AddDays(x.Day.Value);
                    var listEmailLog = DataContext.ReservationRooms.Where(rr => rr.BookingStatus.ToUpper() == "before".ToUpper() && rr.HotelId == x.HotelId && rr.ArrivalDate == dateCompare).Select(y => new HotelEmailLog
                    {
                        Email = y.Travellers.Email,
                        TravellerId = y.TravellerId,
                        HotelId = x.HotelId,
                        Status = (int)SendMailStatus.Processing,
                        HotelEmailTaskId = x.HotelEmailTaskId,
                        ReservationId = y.ReservationId,
                        ReservationRoomId = y.ReservationRoomId
                    }).ToList();
                    result.AddRange(listEmailLog);
                });
            }
            return result;
        }
        #endregion
        #endregion
    }
}